package cn.com.jenson.service.car.service.impl;

import cn.com.jenson.common.ImportVerifierVo;
import cn.com.jenson.common.SelectVo;
import cn.com.jenson.dao.car.bo.CarBo;
import cn.com.jenson.dao.car.searchBo.CarSearchBo;
import cn.com.jenson.dao.car.vo.CarVo;
import cn.com.jenson.entity.car.Car;
import cn.com.jenson.entity.car.QCar;
import cn.com.jenson.entity.user.User;
import cn.com.jenson.exception.BusinessException;
import cn.com.jenson.service.car.repository.CarRepository;
import cn.com.jenson.service.car.service.CarService;
import cn.com.jenson.service.user.repository.UserRepository;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class CarServiceImpl implements CarService {

    @Resource
    private CarRepository carRepository;

    @Resource
    private UserRepository userRepository;

    @Resource
    private JPAQueryFactory jpaQueryFactory;

    QCar qCar = QCar.car;

    @Override
    public Page<CarVo> pageAll(CarSearchBo carSearchBo) {
        JPAQuery<Car> jpaQuery = jpaQueryFactory
                .selectFrom(qCar)
                .where(getWhere(carSearchBo));

        List<Car> list = jpaQuery
                .offset(carSearchBo.getPageRequest().getOffset())
                .limit(carSearchBo.getPageRequest().getPageSize())
                .fetch();

        Page<CarVo> page = new PageImpl<>(
                new CarVo().fromEntities(list, CarVo.class),
                carSearchBo.getPageRequest(),
                jpaQuery.fetchCount()
        );
        supplement(page);

        return page;
    }

    @Override
    public List<CarVo> listAll(CarSearchBo carSearchBo) {
        List<CarVo> list = new CarVo().fromEntities(
                jpaQueryFactory
                        .selectFrom(qCar)
                        .where(getWhere(carSearchBo))
                        .fetch(),
                CarVo.class
        );

        supplement(list);

        return list;
    }

    @Override
    public CarVo get(CarSearchBo carSearchBo) throws InstantiationException, IllegalAccessException {
        CarVo carVo = new CarVo().fromEntity(
                carRepository.findByIdAndDeleted(carSearchBo.getId(), false).orElseThrow(
                        () -> new BusinessException("未找到id为" + carSearchBo.getId() + "的汽车")
                ),
                CarVo.class
        );
        supplement(carVo);
        return carVo;
    }

    @Override
    public BooleanExpression getWhere(CarSearchBo carSearchBo) {
        return qCar.deleted.eq(false);
    }

    @Override
    public CarVo edit(CarBo carBo) throws InstantiationException, IllegalAccessException {
        Car now = carRepository.findByPlateAndDeleted(carBo.getPlate(),false);
        if (Objects.nonNull(now)){
            if (!now.getId().equals(carBo.getId())){
                throw new BusinessException("已存在此车牌");
            }
        }
        Car car = new CarBo().toEntity(carBo, Car.class);
        carRepository.save(car);
        return new CarVo().fromEntity(car, CarVo.class);
    }

    @Override
    public List<CarVo> editAll(List<CarBo> carBos) {
        List<Car> carList = new CarBo().toEntities(carBos, Car.class);
        carRepository.saveAll(carList);
        return new CarVo().fromEntities(carList, CarVo.class);
    }

    @Override
    public CarVo deleted(CarSearchBo carSearchBo) throws InstantiationException, IllegalAccessException {
        Car car = carRepository.findByIdAndDeleted(carSearchBo.getId(), false).orElseThrow(
                () -> new BusinessException("未找到id为" + carSearchBo.getId() + "的汽车")
        );
        car.setDeleted(true);
        carRepository.save(car);
        return new CarVo().fromEntity(car, CarVo.class);
    }

    @Override
    public List<CarVo> deletedAll(List<CarSearchBo> carSearchBos) {
        List<Car> carList = carRepository.findByIdInAndDeleted(
                carSearchBos.stream().map(CarSearchBo::getId).collect(Collectors.toList()),
                false
        );

        carList = carList.stream().peek(item -> item.setDeleted(true)).collect(Collectors.toList());
        carRepository.saveAll(carList);
        return new CarVo().fromEntities(carList, CarVo.class);
    }

    @Override
    public List<ImportVerifierVo> importTemplateVerifiers() {
        return null;
    }

    @Override
    public void importTemplateDownload(HttpServletResponse response) throws IOException {

    }

    @Override
    public List<SelectVo<String, Integer, CarVo>> option() {
        return null;
    }

    @Override
    public void supplement(CarVo carVo) {
        carVo.setUserName(
                userRepository.findByIdAndDeleted(carVo.getUserId(), false).orElse(new User()).getName()
        );
    }

    @Override
    public void supplement(List<CarVo> carVos) {
        List<User> userList = userRepository.findByIdInAndDeleted(
                carVos.stream().map(CarVo::getUserId).collect(Collectors.toList()),
                false
        );
        carVos.forEach(item -> {
            item.setUserName(
                    userList.stream()
                            .filter(user -> Objects.equals(item.getUserId(), user.getId()))
                            .findFirst()
                            .orElse(new User())
                            .getName()
            );
        });
    }

    @Override
    public void supplement(Page<CarVo> carVos) {
        supplement(carVos.getContent());
    }


}
